package com.selenium.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import javax.lang.model.element.Element;

import org.apache.log4j.Logger;




import com.selenium.xls.read.Xls_Reader;



public class DriverScript {

	public static Logger APP_LOGS;
	public static Properties CONFIG;
	public static Properties ELEMENTS;
	// Declare variables for test suite
	public Xls_Reader testSuite;
	public int tsID ;
	public String curTSID;
	public String curTSRunMode;
	public Xls_Reader curTestSuite;
	// Declare variables for test cases
	public int tcID;
	public String curTCName;
	public String curTCRunMode;
	// Declare variables for test Steps;
	public int tstepID;
	public String curTStepsName;
	
	// Declare variables for test data set
	public int tDataSetID;
	public String curtDataSet;
	public ArrayList<String> resultSet;
	public String resultExecute;
	public String curKeyword;
	
	public Keywords keyWords;
	public Method method[];
	
	public String data;
	public String object;
	
	public DriverScript(){
		keyWords = new Keywords();
		method = keyWords.getClass().getMethods();
		
	}
	
	
	public static void main(String args[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException{
		
		DriverScript test = new DriverScript();
		test.initialize();
		test.start();
	}
	
	public void initialize() throws IOException{
		
		// Config properties file
				CONFIG = new Properties();
				FileInputStream fileInput = new FileInputStream(System.getProperty("user.dir")+"//src//com//staffingboss//config//config.properties");
				CONFIG.load(fileInput);
				
				// OR properties
				ELEMENTS = new Properties();
				fileInput = new FileInputStream(System.getProperty("user.dir")+"//src//com//staffingboss//config//elements.properties");
				ELEMENTS.load(fileInput);
				
	}
	
	public void start() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		// initialize the app logs
		APP_LOGS = Logger.getLogger("devpinoyLogger");
		APP_LOGS.debug("Start Debug");
		
		// check the runmode in test suite
		APP_LOGS.debug("Initialize Suite");
		
		testSuite = new Xls_Reader(System.getProperty("user.dir")+ "//src//com//staffingboss//xls//Suite.xlsx");
		
		for (tsID=2; tsID <= testSuite.getRowCount(Constants.TEST_SUITE_SHEET); tsID ++){
			
			curTSID 		= testSuite.getCellData( Constants.TEST_SUITE_SHEET, Constants.TEST_SUITE_ID, tsID) ;
			curTSRunMode    = testSuite.getCellData( Constants.TEST_SUITE_SHEET, Constants.TEST_SUITE_MODE, tsID);
			
			if(curTSRunMode.equals(Constants.RUN_MODE_YES)){
				APP_LOGS.debug("***Executing the test suite :***" + curTSID);
				curTestSuite = new Xls_Reader(System.getProperty("user.dir") + "//src//com//staffingboss//xls//" + curTSID + ".xlsx");
				//System.out.println(curTSID + "--" + System.getProperty("user.dir") + "//src//com//staffingboss//xls//" + curTSID + ".xlsx");
				//System.out.println(curTestSuite.getColumnCount(Constants.TEST_CASE_SHEET));
				// iterate through all the test cases in the suite
				for(tcID=2;tcID<=curTestSuite.getRowCount(Constants.TEST_CASE_SHEET);tcID++){
					
					curTCName 		= curTestSuite.getCellData(Constants.TEST_CASE_SHEET, Constants.TEST_CASE_ID, tcID);
					curTCRunMode 	= curTestSuite.getCellData(Constants.TEST_CASE_SHEET, Constants.TEST_CASE_MODE, tcID);
					System.out.println(curTCName+"----" + curTCRunMode);
					if (curTCRunMode.equals(Constants.RUN_MODE_YES)){
						
						APP_LOGS.debug("*** Executing the test case : ***" + curTCName);
						if(curTestSuite.isSheetExist(curTCName)){
							
							//Run as many time as number of test data sets with runmode Y
							for(tDataSetID=2;tDataSetID<=curTestSuite.getRowCount(curTCName);tDataSetID++){
								
								System.out.println(tDataSetID + "---" + curTestSuite.getRowCount(curTCName) + "Data set:"+ curTestSuite.getCellData(curTCName, "Username" , tDataSetID));
								resultSet = new ArrayList<String>();
								APP_LOGS.debug("Iteration number " + (tDataSetID-1));
								// Checking the runmode for the current dataset
								String curtDataSetMode = curTestSuite.getCellData(curTCName, Constants.TEST_DATASET_MODE , tDataSetID);
								if(curtDataSetMode.equals(Constants.RUN_MODE_YES)){
									
									// iterating through all keywords
									// execute the keywords of test cases
									executeKeywords();
								}
								createXLSReport();
							}
							
						}
						else{
							
							resultSet= new ArrayList<String>(); 
							executeKeywords();// no data with the test
							createXLSReport();
							
						}
					}
						
				}
			}
		}
		
	}

	
	private void executeKeywords() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		
		for (tstepID=2; tstepID <= curTestSuite.getRowCount(Constants.TEST_STEP_SHEET) ; tstepID++ ){
			//Checking TCID
			data   = curTestSuite.getCellData( Constants.TEST_STEP_SHEET , Constants.DATA_PROVIDER , tstepID);
			if (data.startsWith(Constants.DATA_START_COL)){
				// Put the value of column to
				data = curTestSuite.getCellData(curTCName, data.split(Constants.DATA_SPLIT)[1] , tDataSetID );
			}
			object = curTestSuite.getCellData(Constants.TEST_STEP_SHEET, Constants.OBJECT , tstepID);
			
			System.out.println(data);
			System.out.println(object);
			if(curTCName.equals(curTestSuite.getCellData(Constants.TEST_STEP_SHEET, Constants.TEST_CASE_ID, tstepID))){
				
				curKeyword = curTestSuite.getCellData(Constants.TEST_STEP_SHEET, Constants.KEY_WORDS , tstepID);
				APP_LOGS.debug(curKeyword);
				
				// Execute all keywords ( for example: write the function to execute keyword OpenBrowser, ClickLink, .. in here)
				// Reflection API testing
				for (int i= 0; i < method.length ; i++){
					System.out.println(method[i].getName());
					if(method[i].getName().equals(curKeyword)){
						resultExecute = (String)method[i].invoke(keyWords , object , data);
						APP_LOGS.debug(resultExecute);
						resultSet.add(resultExecute);// <== used for add result of execution to the test 
					}
				}
				
			}	
		}
		
	}

	
	private void createXLSReport() {
		// TODO Auto-generated method stub
		String colName=Constants.RESULT +(tDataSetID-1);
		System.out.println("hey this is my column name");
		System.out.println(colName); 
		System.out.println(curTestSuite.getColumnCount(Constants.TEST_STEP_SHEET));
		boolean isColExist=false;
		
		for(int c=0;c<curTestSuite.getColumnCount(Constants.TEST_STEP_SHEET);c++){
			System.out.println("****");
			System.out.println(curTestSuite.getCellData(Constants.TEST_STEP_SHEET,c , 2));
			System.out.println(curTestSuite.getCellData(Constants.TEST_STEP_SHEET,c , 1));
			System.out.println(colName);
			System.out.println("$$$$");
			if(curTestSuite.getCellData(Constants.TEST_STEP_SHEET,c , 1).equals(colName)){
				isColExist=true;
				break;
			}
		}
		
		if(!isColExist)
			curTestSuite.addColumn(Constants.TEST_STEP_SHEET, colName);
		System.out.println(Constants.TEST_STEP_SHEET);
		System.out.println(colName);
		int index=0;
		for(int i=2; i<=curTestSuite.getRowCount(Constants.TEST_STEP_SHEET); i++){
			
			if(curTCName.equals(curTestSuite.getCellData(Constants.TEST_STEP_SHEET, Constants.TEST_CASE_ID , i))){
				if(resultSet.size()==0)
					curTestSuite.setCellData(Constants.TEST_STEP_SHEET, colName, i, Constants.SKIP);
				else	
					curTestSuite.setCellData(Constants.TEST_STEP_SHEET, colName, i, resultSet.get(index));
				index++;
			}
		}
		
		if(resultSet.size()==0){
			// skip
			curTestSuite.setCellData(curTCName, Constants.RESULT, tDataSetID, Constants.SKIP);
			return;
		}else{
			for(int i=0;i<resultSet.size();i++){
				if(!resultSet.get(i).equals(Constants.PASS)){
					curTestSuite.setCellData(curTCName, Constants.RESULT, tDataSetID, Constants.FAIL);
					return;
				}
			}
		}
		curTestSuite.setCellData(curTCName, Constants.RESULT, tDataSetID, Constants.PASS);
	}

}
